/*
 * @Author: xiaosihan
 * @Date: 2022-08-20 14:50:15
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-10-30 19:33:59
 */
import { AmbientLight, Color, DirectionalLight, LinearFilter, NoBlending, PointLight, RGBAFormat, ShaderChunk, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget } from 'three';
import ThreeBase from 'three-base';
import SiChuanMap from './SiChuanMap/SiChuanMap';
import { autorun } from 'mobx';
import { fullScreenMesh } from 'three-base/shaders';
import siChuanMap3DStore from './chengduMap3DStore';
import utils from '@utils';

// 四川地图渲染器
class SichuanMapRender extends ThreeBase {
  constructor() {
    super();
  }

  // 环境光
  ambientLight = (() => {
    const ambientLight = new AmbientLight('#fff', 0.3);
    this.scene.add(ambientLight);
    return ambientLight;
  })();

  //点光源
  pointLight = (() => {
    const pointLight = new PointLight('#fff', 0.3);
    pointLight.position.set(50, 40, 50);
    this.scene.add(pointLight);
    return pointLight;
  })();

  // 方向光
  directionalLight = (() => {
    const directionalLight = new DirectionalLight('#fff', 0.3);
    directionalLight.position.set(-10, 10, 5);
    directionalLight.target.position.set(0, 0, 0);
    directionalLight.castShadow = true;
    directionalLight.shadow.mapSize.set(1024, 1024);
    this.scene.add(directionalLight);
    return directionalLight;
  })();

  disposer = autorun(() => {
    const { areaCode } = siChuanMap3DStore;

    switch (areaCode) {
      // 四川视角
      case 510000:
        this.setLookAt({
          center: new Vector3(-0.62, -0.055, 0.102),
          position: new Vector3(-0.632, 12.637, 1.458),
        });
        break;
      // 成都视角
      case 510100:
        this.setLookAt({
          center: new Vector3(0.785, 0.324, -0.497),
          position: new Vector3(0.953, 2.273, 0.575),
        });
        break;

      // 凉山视角
      case 513400:
        this.setLookAt({
          position: new Vector3(-1.089, 3.205, 5.738),
          center: new Vector3(-1.465, -1.37, 1.324),
        });
        break;

      // 甘孜视角
      case 513300:
        this.setLookAt({
          center: new Vector3(-3.848, 0.157, -0.356),
          position: new Vector3(-3.862, 8.946, 4.151),
        });
        break;

      // 阿坝视角
      case 513200:
        this.setLookAt({
          position: new Vector3(-0.789, 4.868, 0.952),
          center: new Vector3(-0.974, 0.105, -2.021),
        });
        break;

      default:
        break;
    }
  });

  init() {
    super.init();
    this.resetLookAt({
      center: new Vector3(0.785, 0.324, -0.497),
      position: new Vector3(0.953, 2.273, 0.575),
    });
    this.controls.enabled = utils.isDev;
  }

  // 四川地图
  siChuanMap = (() => {
    const siChuanMap = new SiChuanMap();

    //three事件
    siChuanMap.userData = {
      cursor: 'pointer',
      enableEvent: false,
      cover_enable: true, //启用描边
      cover_color: '#04fa12', //描边颜色
      cover_opacity: 10, //描边厚度(像素)
    };

    this.scene.add(siChuanMap);
    return siChuanMap;
  })();

  // 发光渲染对象
  glowRenderTerget = new WebGLRenderTarget(128, 128, { minFilter: LinearFilter, magFilter: LinearFilter, format: RGBAFormat });

  // 提取边缘线着色器
  extractEdgeShader = new ShaderMaterial({
    uniforms: {
      map: { value: null }, // 被提取的纹理
      width: { value: 1 }, // 提取的宽度
      color: { value: new Color('#fff') }, // 提取出来的边缘的颜色
      resolution: { value: new Vector2(512, 512) }, // 分辨率
    },
    vertexShader: `
        ${ShaderChunk.common}
        ${ShaderChunk.logdepthbuf_pars_vertex}
        varying vec2 vUv;
        void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            ${ShaderChunk.logdepthbuf_vertex}
        }
    `,
    fragmentShader: `
        ${ShaderChunk.logdepthbuf_pars_fragment}
        #include <common>
        uniform sampler2D map;
        uniform float width;
        uniform vec3 color;
        uniform vec2 resolution;
        varying vec2 vUv;

        // 二维向量的绕点旋转的方法
        vec2 rotateAround( vec2 p, vec2 center, float angle ) {
            float c = cos( angle );
            float s = sin( angle );
            float x = p.x - center.x;
            float y = p.y - center.y;
            p.x = x * c - y * s + center.x;
            p.y = x * s + y * c + center.y;
            return p;
        }

        void main() {
            float alpha = texture2D(map, vUv).a;
            if(alpha < 0.2){
                discard;                
            }

            float opacity = 1.0;
            
            for(float i = 0.0; i < 2.0; i+= 0.1){
                opacity = min(opacity,  texture2D(map,  rotateAround( (vec2(1.0, 0.0) / resolution * width)+ vUv, vUv , PI * i) ).a);
                if(opacity < 0.2){
                    break;
                }
            }

            if( opacity < 0.2 ){
                gl_FragColor = vec4(color, 1.0);
            }else{
                discard;
                // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
            }

            // gl_FragColor = texture2D(map, vUv);
            ${ShaderChunk.logdepthbuf_fragment}
        }
    `,
    blending: NoBlending, // 渲染时不与背景融合计算 直接替换
    depthTest: true,
    depthWrite: true,
    transparent: true,
  });

  // 提取离屏渲染对象的边缘
  extractEdge(renderTerget: WebGLRenderTarget, width: number, color: string = '#00ff00') {
    this.copyTextureToRenderTarget(renderTerget.texture, this.renderTarget2, true); // 拷贝并覆盖渲染目标

    const originTarget = this.renderer.getRenderTarget();

    this.clearRendererTargte(renderTerget);
    this.renderer.setRenderTarget(renderTerget);

    fullScreenMesh.material = this.extractEdgeShader;
    this.extractEdgeShader.uniforms.map.value = this.renderTarget2.texture;
    this.extractEdgeShader.uniforms.width.value = width;
    this.extractEdgeShader.uniforms.color.value.set(color);
    fullScreenMesh.render(this.renderer);

    this.renderer.setRenderTarget(originTarget);
  }

  // 渲染描边光效
  renderGlow() {
    this.renderer.clearDepth(); // 清理渲染器的深度
    // const color = {
    //     origin: "#EECD3A",
    //     green: "#5FE2F8"
    // }
    // 渲染整个地图的绿色辉光
    this.object3dToRendererTarget(this.siChuanMap, this.glowRenderTerget); // 把地图渲染到离屏渲染对象上面
    this.extractEdge(this.glowRenderTerget, 2, '#B5E4FF'); // 提取地图边缘
    this.renderTargetAddGlow(this.glowRenderTerget, 2, '#B5E4FF'); // 5px 的辉光
    this.renderRendererTarget(this.glowRenderTerget); // 把辉光渲染目标渲染到渲染器上面
  }

  render() {
    super.render();
    const { areaCode } = siChuanMap3DStore;
    if (areaCode === 510000) {
      this.renderGlow();
    }
  }
}

const sichuanMapRender = (window.sichuanMapRender = new SichuanMapRender());

export default sichuanMapRender;
